/**
******************************************************************************
* @file    app_menu_cfg.c
* @author  MCD Application Team
* @brief   Configuration interface of menu for application
******************************************************************************
* @attention
*
* Copyright (c) 2020-2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/

/* Includes ------------------------------------------------------------------*/
#include "app_entry.h"
#include "app_ble.h"
#include "p2p_server_app.h"
#include "app_menu_cfg.h"
#include "app_menu.h"
#include "app_conf.h"
#include "ble_gap_aci.h"
#include "log_module.h"
#include "stm32_timer.h"
#include "stm32_seq.h"

/* External variables ------------------------------------------------------- */
extern uint8_t advertising_byteicon[];
extern uint8_t hourglass_byteicon[];
extern uint8_t input_byteicon[];
extern uint8_t input_output_byteicon[];
extern uint8_t output_byteicon[];
extern uint8_t bluetooth_byteicon[];
extern uint8_t stlogo_byteicon[];
extern uint8_t homelogo_byteicon[];
extern uint8_t arrow_right_byteicon[];
extern uint8_t arrow_up_byteicon[];
extern uint8_t arrow_down_byteicon[];
extern uint8_t arrow_return_byteicon[];

/* Private defines ---------------------------------------------------------- */
#define STARTUP_TIMEOUT                 (1500u)

/* Private variables -------------------------------------------------------- */
Menu_Icon_t access_menu_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &arrow_right_byteicon, 16, 16, 0};
Menu_Icon_t return_menu_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &arrow_return_byteicon, 8, 8, 0};
Menu_Icon_t up_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &arrow_up_byteicon, 16, 16, 0};
Menu_Icon_t down_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &arrow_down_byteicon, 16, 16, 0};
Menu_Icon_t homelogo_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &homelogo_byteicon, 128, 64, 0};
Menu_Icon_t bluetooth_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &bluetooth_byteicon, 16, 16, 0};
Menu_Icon_t stlogo_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &stlogo_byteicon, 16, 16, 0};
Menu_Icon_t advertising_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &advertising_byteicon, 16, 16, 0};
Menu_Icon_t hourglass_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &hourglass_byteicon, 16, 16, 0};
Menu_Icon_t input_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &input_byteicon, 16, 16, 0};
Menu_Icon_t input_output_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &input_output_byteicon, 16, 16, 0};
Menu_Icon_t output_icon = {MENU_ICON_TYPE_IMAGE, (uint8_t *) &output_byteicon, 16, 16, 0};

Menu_Content_Text_t startup_text_bank1 = {4, {"BLE OTA dual bank", "p2p Server", "application", "running on bank 1"}};
Menu_Content_Text_t startup_text_bank2 = {4, {"BLE OTA dual bank", "p2p Server", "application", "running on bank 2"}};

Menu_Content_Text_t p2pS_text = {4, {"Advertising", "", "LED level 0", "press > to notify"}};

Menu_Content_Text_t flash_text_valid = {4, {"FW into bank x", "is valid", "press > to", "reboot on bank x"}};
Menu_Content_Text_t flash_text_invalid = {2, {"FW into bank x", "is not valid"}};

Menu_Content_Text_t fw_update_text = {4, {"FW update on going", "", "", ""}};

Menu_Page_t *p_stlogo_page;
Menu_Page_t *p_startup_page;
Menu_Page_t *p_entry_page;
Menu_Page_t *p_p2pS_page;
Menu_Page_t *p_flash_page;
Menu_Page_t *p_fw_update_page;
Menu_Page_t *p_before_ota_page;

Menu_Action_t action_go_before_ota_page = {MENU_ACTION_MENU_PAGE, &return_menu_icon, 0, 0};

#if (CFG_JOYSTICK_SUPPORTED == 1)
static UTIL_TIMER_Object_t Startup_Timer;
#endif /* (CFG_JOYSTICK_SUPPORTED == 1) */


/* Private functions prototypes-----------------------------------------------*/
static void Menu_p2ps_notif_cb(void);
static void Menu_Flash_Swap_cb(void);

#if (CFG_JOYSTICK_SUPPORTED == 1)
static void Menu_Startup_TimerCallback(void *arg);
#endif /* (CFG_JOYSTICK_SUPPORTED == 1) */
/* Exported Functions Definition -------------------------------------------- */
/**
 * @brief Initialize and setup the menu
 */
void Menu_Config(void)
{
 
  
  
  /* creation of actions ---------------------------------------------------- */
  Menu_Action_t action_go_entry_page    = {MENU_ACTION_MENU_PAGE, &access_menu_icon, 0, 0};
  Menu_Action_t action_go_p2pS_page     = {MENU_ACTION_MENU_PAGE, &access_menu_icon, 0, 0};
  Menu_Action_t action_go_flash_page    = {MENU_ACTION_MENU_PAGE, &access_menu_icon, 0, 0};
  Menu_Action_t action_p2ps_page_notif  = {MENU_ACTION_CALLBACK, &access_menu_icon, &Menu_p2ps_notif_cb, 0, 0};
  Menu_Action_t action_flash_page_swap  = {MENU_ACTION_CALLBACK, &access_menu_icon, &Menu_Flash_Swap_cb, 0, 0};

  Menu_Init();

  /* creation of pages ------------------------------------------------------ */
  p_stlogo_page = Menu_CreatePage(MENU_TYPE_LOGO);
  p_startup_page = Menu_CreatePage(MENU_TYPE_CONTROL);
  p_entry_page = Menu_CreatePage(MENU_TYPE_LIST);
  p_p2pS_page = Menu_CreatePage(MENU_TYPE_CONTROL);
  p_flash_page = Menu_CreatePage(MENU_TYPE_CONTROL);
  p_fw_update_page = Menu_CreatePage(MENU_TYPE_CONTROL);

  /* Actions configuration -------------------------------------------------- */
  action_go_entry_page.pPage = (struct Menu_Page_t*) p_entry_page;
  action_go_p2pS_page.pPage = (struct Menu_Page_t*) p_p2pS_page;
  action_go_flash_page.pPage = (struct Menu_Page_t*) p_flash_page;
  
  /* Pages configuration ---------------------------------------------------- */
  Menu_SetLogo(p_stlogo_page, &homelogo_icon);
  
  /* startup page */
  Menu_SetControlAction(p_startup_page, MENU_DIRECTION_RIGHT, action_go_entry_page);  
  if( APPE_get_active_flash_bank() == 1)
  {
    Menu_SetControlContent(p_startup_page, &startup_text_bank1, 0);
  }
  else
  {
    Menu_SetControlContent(p_startup_page, &startup_text_bank2, 0);
  }

  /* entry page */
  Menu_AddListEntry(p_entry_page, "p2pServer", action_go_p2pS_page);
  Menu_AddListEntry(p_entry_page, "Flash", action_go_flash_page);

  /* p2pServer page */
  Menu_SetControlContent(p_p2pS_page, &p2pS_text, 0);
  Menu_SetControlAction(p_p2pS_page, MENU_DIRECTION_RIGHT, action_p2ps_page_notif);
  
  /* flash page */
  if(APPE_get_active_flash_bank() == 1)
  {
    strcpy((char*)&flash_text_invalid.Lines[0], "FW into bank 2");
    strcpy((char*)&flash_text_valid.Lines[0], "FW into bank 2");
    strcpy((char*)&flash_text_valid.Lines[3], "reboot on bank 2");
  }
  else
  {
    strcpy((char*)&flash_text_invalid.Lines[0], "FW into bank 1");
    strcpy((char*)&flash_text_valid.Lines[0], "FW into bank 1");
    strcpy((char*)&flash_text_valid.Lines[3], "reboot on bank 1");
  }

  if(APPE_check_FW_opposite_bank_validity() == 1)
  {
    Menu_SetControlContent(p_flash_page, &flash_text_valid, 0);
    Menu_SetControlAction(p_flash_page, MENU_DIRECTION_RIGHT, action_flash_page_swap);
  }
  else
  {
    Menu_SetControlContent(p_flash_page, &flash_text_invalid, 0);
  }

  /* FW update page */
  Menu_SetControlContent(p_fw_update_page, &fw_update_text, 0);
  Menu_SetControlAction(p_fw_update_page, MENU_DIRECTION_LEFT, action_go_before_ota_page);

  /* start menu */
  Menu_SetActivePage(p_stlogo_page);
  UTIL_TIMER_Create(&Startup_Timer, STARTUP_TIMEOUT, UTIL_TIMER_ONESHOT, &Menu_Startup_TimerCallback, 0);
  UTIL_TIMER_Start(&Startup_Timer);
}

/**
 * @brief Set the Startup Page as active
 */
void Menu_SetStartupPage(void)
{
  Menu_SetActivePage(p_startup_page);
}

void Menu_p2pS_page_update(void)
{
  if( P2P_getLedStatus() == 0 )
  {
    strcpy((char*)&p2pS_text.Lines[2], "LED level 0");
  }
  else
  {
    strcpy((char*)&p2pS_text.Lines[2], "LED level 1");
  }
  
  if( APP_BLE_Get_Server_Connection_Status() == APP_BLE_CONNECTED_SERVER)
  {
    strcpy((char*)&p2pS_text.Lines[0], "Connected");
  }
  else
  {
    strcpy((char*)&p2pS_text.Lines[0], "Advertising");
  }  
    
  Menu_Print();
}

void Menu_fw_update_page_update(uint32_t code)
{
  
  switch (code)
  {
    case MENU_UPDATE_CODE_APP_START_ERASE:
    case MENU_UPDATE_CODE_USER_CONF_START_ERASE:
    {
      p_before_ota_page = Menu_GetActivePage();
      strcpy((char*)&fw_update_text.Lines[1], "Erasing...");
      Menu_SetActivePage(p_fw_update_page);
    }
    break;
    case MENU_UPDATE_CODE_APP_START_FLASH:
    case MENU_UPDATE_CODE_USER_CONF_START_FLASH:
    {
      strcpy((char*)&fw_update_text.Lines[1], "Flashing...");
    }
    break;
    case MENU_UPDATE_CODE_APP_END_SUCCESS:
    case MENU_UPDATE_CODE_USER_CONF_END_SUCCESS:
    {
      strcpy((char*)&fw_update_text.Lines[1], "Update done Success");
    }
    break;
    case MENU_UPDATE_CODE_APP_END_FAIL:
    case MENU_UPDATE_CODE_USER_CONF_END_FAIL:
    {
      action_go_before_ota_page.pPage = (struct Menu_Page_t*) p_before_ota_page;
      Menu_SetControlAction(p_fw_update_page, MENU_DIRECTION_LEFT, action_go_before_ota_page);
      
      strcpy((char*)&fw_update_text.Lines[1], "Update Failling");
    }
    break;
    default:
    break;
  }

  Menu_Print();
}

/* Private Functions Definition --------------------------------------------- */
/**
 * @brief p2pServer send notification action callback
 */
static void Menu_p2ps_notif_cb(void)
{
  LOG_INFO_APP("[APP_MENU_CONF] p2pServer send notification callback\n");

  if (APP_BLE_Get_Server_Connection_Status() == APP_BLE_CONNECTED_SERVER)
  {
    UTIL_SEQ_SetTask( 1 << CFG_TASK_SEND_NOTIF_ID, CFG_SEQ_PRIO_0);
  }
}

/**
 * @brief Flash bank swap callback
 */
static void Menu_Flash_Swap_cb(void)
{
  LOG_INFO_APP("[APP_MENU_CONF] Flash bank swap callback\n");
 
  if(APPE_check_FW_opposite_bank_validity() != 0)
  {
    LOG_INFO_APP("Swapping booting flash bank, MCU will reset\n");
    APPE_swap_flash_bank();
  }
  else
  {
    LOG_INFO_APP("Application present in opposite bank is not valid\n");
  }
}

#if (CFG_JOYSTICK_SUPPORTED == 1)
/**
 * @brief Startup Timer Callback
 */
static void Menu_Startup_TimerCallback(void *arg)
{
  LOG_INFO_APP("[APP_MENU_CONF] Startup timer expired, Display home\n");
  Menu_SetStartupPage();
}
#endif /* (CFG_JOYSTICK_SUPPORTED == 1) */
